import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;
import java.nio.FloatBuffer;
import java.util.Date;
public class Main {
	//VARIABLES
	private static boolean framelimiter = true;
	private static boolean lwjglLimiter = true;
	private static int FRAMELIMIT = 60;
	private static boolean CALCULATEFPS =false;
	//
	private static boolean done=false;
	private static Box box1;
	//-TimeKeeper Vars--//
	public static int FRAMENANOS = 1000000000/FRAMELIMIT;
	private static long lastFrame;
	private static long waittime = 0;
	private static int framerate_count = 0;
	private static long framerate_timestamp = new Date().getTime();
	//--
	
	public static void main(String[] args) {
		init();
		while(!done){
            if(Display.isCloseRequested())
            done=true;
            int delta = getDelta();
            
            timeMgmt(delta);
            render(delta);
            
            Display.update();
        }
        Display.destroy();
	}
	private static void init(){
		int w=1024;
        int h=768;	
		try {
				Display.setDisplayMode(new DisplayMode(w, h));
				Display.setVSyncEnabled(true);
				Display.setTitle("Shader Setup "+FRAMENANOS);
				Display.create();
				Display.setResizable(true);
			} catch (LWJGLException e) {
				e.printStackTrace();
				System.exit(0);
			}
	    // set up OpenGL
	    GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	    GL11.glShadeModel(GL11.GL_SMOOTH);

	    GL11.glEnable(GL11.GL_COLOR_MATERIAL);
	    GL11.glEnable(GL11.GL_DEPTH_TEST);
	    //AA
	    GL11.glEnable(GL11.GL_LINE_SMOOTH);
	    GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
	    GL11.glEnable(GL11.GL_BLEND);
	    //
	    GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
	    GL11.glEnableClientState(GL11.GL_NORMAL_ARRAY);
	    GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
	    //
	    // set up lighting
	    //LIGHTING
	    GL11.glEnable(GL11.GL_LIGHTING);
	    GL11.glEnable(GL11.GL_LIGHT0);
	    
	    FloatBuffer buff1 = BufferUtils.createFloatBuffer(4).put(new float[] {1.0f, 1.0f, 1.0f, 1.0f});
	    buff1.rewind();
	    
	    GL11.glMaterial(GL11.GL_FRONT, GL11.GL_SPECULAR, buff1);
	    GL11.glMaterialf(GL11.GL_FRONT, GL11.GL_SHININESS, 25.0f);

	    buff1 = BufferUtils.createFloatBuffer(4).put(new float[] {-5.0f, 5.0f, 15.0f, 0.0f});
	    buff1.rewind();
	    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, buff1);
	    
	    buff1 = BufferUtils.createFloatBuffer(4).put(new float[] {1.0f, 1.0f, 1.0f, 1.0f});
	    buff1.rewind();
	    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_SPECULAR, buff1);
	    GL11.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, buff1);

	    buff1 = BufferUtils.createFloatBuffer(4).put(new float[] {0.3f, 0.3f, 0.3f, 1.0f});
	    buff1.rewind();
	    GL11.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, buff1);

	    // set up the camera
	    GL11.glMatrixMode(GL11.GL_PROJECTION);
	    GL11.glLoadIdentity();
	    GLU.gluPerspective(45.0f, 1.0f, 0.1f, 100.0f);
	    GL11.glMatrixMode(GL11.GL_MODELVIEW);
	    GL11.glLoadIdentity();
	    GLU.gluLookAt(
	    	      0.0f,
	    	      0.0f,
	    	      5.0f,
	    	      0.0f,
	    	      0.0f,
	    	      0.0f,
	    	      0.0f,
	    	      1.0f,
	    	      0.0f
	    );
	    if(Sys.is64Bit()){
	    	System.out.println("You are running in x64 bit mode");
	    }else{
	    	System.out.println("You are running in x32 bit mode");
	    }
	    box1 = new Box(FRAMENANOS);
		//setup things

	    pyramid pyro2 = new pyramid(box1,"pyramid");
	    pyramid pyro3 = new pyramid(box1,"cube");
	}
	private static void render(int delta){
		pollInput();
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT |
        GL11.GL_DEPTH_BUFFER_BIT);
        GL11.glLoadIdentity();
        box1.draw(delta,getTime());
    }
	private static void pollInput() {
		while (Keyboard.next()) {
			if (Keyboard.getEventKeyState()) {
				
				if (Keyboard.getEventKey() == Keyboard.KEY_A) {	
					System.out.println("A Key Pressed");
					box1.inputhand(1);
				}
				if (Keyboard.getEventKey() == Keyboard.KEY_S) {
					System.out.println("S Key Pressed");
					box1.inputhand(2);
				}
				if (Keyboard.getEventKey() == Keyboard.KEY_W) {
					box1.inputhand(3);
				}
				if (Keyboard.getEventKey() == Keyboard.KEY_E) {
					box1.inputhand(4);
				}
				if (Keyboard.getEventKey() == Keyboard.KEY_L) {
					box1.inputhand(5);
				}
			} else {
				if (Keyboard.getEventKey() == Keyboard.KEY_A) {
					System.out.println("A Key Released");
				}
				if (Keyboard.getEventKey() == Keyboard.KEY_S) {
					System.out.println("S Key Released");
				}
				if (Keyboard.getEventKey() == Keyboard.KEY_D) {
					System.out.println("D Key Released");
				}
			}
		}
	}
	//--------Timers
	private static int getDelta() {
	    long time = getTime();
	    int delta = (int) (time - lastFrame);
	    lastFrame = time;
	   
	    return delta;
	}
	//return The system time in milliseconds
	public static long getTime() {
	    return (System.nanoTime());
	}
	private static void timeMgmt(int delta){
		if(CALCULATEFPS == true){
			Date d = new Date();
	    	framerate_count++;
	        long this_framerate_timestamp = d.getTime();
	        if ((this_framerate_timestamp - framerate_timestamp) >= 1000) {
	          System.err.println("Frame Rate: " + framerate_count);
	          framerate_count = 0;
	          framerate_timestamp = this_framerate_timestamp;
	        }
		}
		//ideal, delta = 16666666 1000000000/FRAMELIMIT		
		if(framelimiter == true){
			if(lwjglLimiter == true){
				Display.sync(FRAMELIMIT);
			}else{
				if(delta < 1000000000/FRAMELIMIT){
					waittime += 1;
				}else if(delta > 1000000000/FRAMELIMIT){
					waittime -= 1;
				}
				if(waittime > 0){
					try {
						Thread.sleep(waittime);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
	//----
}
